package com.atom.module.lib.opengles.texture

import android.opengl.GLES11Ext
import android.opengl.GLES30
import com.atom.module.lib.opengles.draw.GlBindable
import com.atom.module.lib.opengles.draw.use
import com.atom.module.lib.opengles.util.ShaderUtils
import kotlin.jvm.JvmOverloads

 class GlTexture private constructor(
     val unit: Int,
     val target: Int,
     id: Int?,
     val width: Int?,
     val height: Int?,
     val format: Int?,
    internalFormat: Int?,
     val type: Int?
) : GlBindable {

    @JvmOverloads
     constructor(
        unit: Int = GLES30.GL_TEXTURE0,
        target: Int = GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
        id: Int? = null
    ): this(unit, target, id, null, null, null, null, null)

    @Suppress("unused")
    @JvmOverloads
     constructor(
        unit: Int, target: Int, width: Int, height: Int,
        format: Int = GLES30.GL_RGBA,
        internalFormat: Int = format,
        type: Int = GLES30.GL_UNSIGNED_BYTE
    ): this(unit, target, null, width, height, format, internalFormat, type)

     val id: Int = id ?: run {
        val textures = IntArray(1)
        GLES30.glGenTextures(1, textures, 0)
        ShaderUtils.checkGLError("glGenTextures")
        textures[0]
    }

    init {
        if (id == null) {
            use {
                if (width != null && height != null
                    && format != null
                    && internalFormat != null
                    && type != null
                ) {
                    GLES30.glTexImage2D(
                        target,
                        0,
                        internalFormat,
                        width,
                        height,
                        0,
                        format.toInt(),
                        type.toInt(),
                        null
                    )
                }

                GLES30.glTexParameteri(target, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST)
                GLES30.glTexParameteri(target, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
                GLES30.glTexParameteri(target, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
                GLES30.glTexParameteri(target, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)

                ShaderUtils.checkGLError("glTexParameter")
            }
        }
    }

    override fun bind() {
        GLES30.glActiveTexture(unit)
        GLES30.glBindTexture(target, id)
        ShaderUtils.checkGLError("bind")
    }

    override fun unbind() {
        GLES30.glBindTexture(target, 0)
        GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
        ShaderUtils.checkGLError("unbind")
    }

     fun release() {
        GLES30.glDeleteTextures(1, intArrayOf(id), 0)
    }
}